perm filename IMPUDP[IP,SYS] blob sn#741324 filedate 1984-02-05 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00006 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.FATAL This code is far from ready.  -- JJW
C00003 00003	Initialize UDP service  UDPINI
C00004 00004	MTAPE to write a UDP packet  UDPWRT UDPWR1 UDPWR2 UDPWR3
C00008 00005	MTAPE to read a UDP packet.  UDPREA STTERR UDPRE1 UDPRED UDPFLS UDPREW
C00013 00006	MTAPE to get a free UDP local port number, stored in word 1 of MTAPE block  GENUDP UDPPRT UDPPR1 UDPPR2
C00017 ENDMK
C⊗;
.FATAL This code is far from ready.  -- JJW

Comments:

The following code contains TCP assumptions and must be fixed for UDP:

In NETSUB: BIBMAK sets up retransmission.

;IMPSER code for UDP protocol

;Definitions

UDRPRT←←400			;Reserve ports 0-377

;Storage

UDFPRT:	BLOCK 1			;Last UDP free port assigned

;Initialize UDP service ;⊗ UDPINI

UDPINI:	MOVEI TAC,UDRPRT
	MOVEM TAC,UDFPRT
	POPJ P,

;MTAPE to write a UDP packet ;⊗ UDPWRT UDPWR1 UDPWR2 UDPWR3

;	MTAPE <chan>,ADR
;ADR:	30
;	<status bits returned>
;	<local port>
;	<user addr of packet data>
;	<packet length>
;	<foreign port>
;	<foreign host>

UDPWRT:	XCTR XR,[SKIPLE DAT,BSLOC(UUO)]	;Get packet length
;JJW - get right max packet size
	CAILE DAT,=512			;Range check
	JRST ADRERR			;Address check if bad length
	MOVEI TAC,3(DAT)		;Round up to words
	LSH TAC,-2
	XCTR XR,[MOVE TAC1,WFLOC(UUO)]	;Get user buffer address
	ADDI TAC1,-1(TAC)		;Last word in buffer
	XCTR XR,[MOVE TAC,(TAC1)]	;Address check
	XCTR XR,[MOVE TAC1,WFLOC(UUO)]	;Get buffer address again
	HRLI TAC1,441000		;Make 8-bit byte ptr
	XCTR XR,[SKIPGE TAC,LSLOC(UUO)]	;Get local port from user
	PUSHJ P,UDPPRT			;He wants us to make one
	ANDI TAC,177777			;Make it legal
	MOVEM TAC,LCLPRT(DDB)
	XCTR XW,[MOVEM TAC,LSLOC(UUO)]	;Tell him the port
	XCTR XR,[MOVE TAC,FSLOC(UUO)]	;Get foreign port
	ANDI TAC,177777
	MOVEM TAC,RMTPRT(DDB)
	XCTR XR,[MOVE TAC,HLOC(UUO)]	;Get foreign host
	MOVEM TAC,RMTADR(DDB)
	PUSHJ P,SAVALL		;Enter TOPS-10 mode
	SETAC(T1,TAC)		;Get foreign host address
	PUSHJ P,TARGET↑		;Find a place to send this packet
	 JRST CGTERR		;Can't get there
	MOVEM T1,NETADR(F)
	MOVEM W,NETWRK(F)
	;Now copy the data into IMP buffers (byte-by-byte, as we checksum)
	;and send it out.
	SETAC(P1,TAC1)		;Starting address
	SETAC(P2,DAT)		;Length in bytes
	;P3 accumulates the checksum
	MOVEI P4,OUBYTE↑	;Coroutine linkage
UDPWR1:	XCTR XLB,[ILDB T1,P1]	;Get a byte
	JSP P4,(P4)		;Store it
	 JRST UDPWR3		;Error (no more buffers)
	SOJG P2,UDPWR1		;Loop for more
	PUSHJ P,OUTBFX↑		;Link last buffer to stream
	OFFSCN			;Blecchhh
	PUSHJ P,OUTPRE↑		;Ensure enough room (UDP takes less than TCP,
				;so OUTPRE is usable).
	 JRST UDPWR2		;Not enough, lose
	PUSHJ P,UDPMAK↑		;Send it away!
	JRST SCNONJ		;That's all, folks

UDPWR2:	ONSCN
UDPWR3:	MOVE T1,OBFFST(F)	;Point to beginning of stream
	PUSHJ P,RELBUF↑		;Flush it all
	SETZM OBFFST(F)
	POPJ P,			;Just return
;MTAPE to read a UDP packet. ;⊗ UDPREA STTERR UDPRE1 UDPRED UDPFLS UDPREW

;	MTAPE <chan>,ADR
;ADR:	31			;Read or request a UDP packet
;	<status bits returned>
;	<local port>
;	<user addr of packet data>
;	<packet length returned>
;	<foreign port>
;	<foreign host>

UDPREA:	MOVEI TAC,.IPUDP	;IP protocol code for UDP
	CAME TAC,PROTCL(DDB)	;Check protocol in DDB
	SKIPN STATE(DDB)	;Not UDP, but OK if closed
	JRST UDPRE1		;Jump if DDB state OK
STTERR:	MOVEI TAC,E.STT↑	;Code for state error (defined in TCPSER.MAC)
	XCTR XW,[MOVEM TAC,STLOC(UUO)]
	POPJ P,

UDPRE1:	MOVEM TAC,PROTCL(DDB)	;Now we're in UDP for sure
	XCTR XW,[SETZM STLOC(UUO)]	;No errors yet
	SKIPE IBFTHS(DDB)	;Flush any currently waiting packet
	PUSHJ P,UDPFLS
	SETOM IBFTHS(DDB)	;Lock out packet input
	XCTR XR,[MOVE TAC,LSLOC(UUO)]	;Copy local port to DDB
	MOVEM TAC,LCLPRT(DDB)
	XCTR XR,[MOVE TAC,FSLOC(UUO)]	;Copy foreign port to DDB
	MOVEM TAC,RMTPRT(DDB)
	XCTR XR,[MOVE TAC,HLOC(UUO)]	;Copy foreign host to DDB
	MOVEM TAC,RMTADR(DDB)
	MOVSI IOS,IDATWT	;Set wait bit
	IORB IOS,DEVIOS(DDB)
	SETZM IBFTHS(DDB)	;Allow new packet to arrive
;Enter here for MTAPE to wait for previously requested packet.
UDPRED:	PUSHJ P,SAVALL		;Enter TOPS-10 mode
	XCTR XR,[SKIPE P4,WFLOC(UUO)]	;See if user buffer given
	PUSHJ P,UDPREW		;Wait for packet or error
	 POPJ P,		;No buffer or error (probably timeout)
	SKIPN P1,IBFTHS(F)	;Make sure there really is a packet
	POPJ P,			;No, there isn't
	MOVE P2,MSGLEN(F)	;Get packet length
	XCTR XW,[MOVEM P2,BSLOC(F)]	;Return in MTAPE block
	ADDI P2,3		;Round up to multiple of 4
	LSH P2,-2		;Convert bytes to words
UDPRE2:	MOVSI T1,NBHLEN(P1)	;Source for BLT
	HRRI T1,(P4)		;Destination
	MOVEI T2,IMPBFS-NBHLEN	;Number of data words in an IMP buffer
	CAILE T2,(P2)		;Number of words to BLT
	MOVEI T2,(P2)
	SUBI P2,(T2)		;Decrement count
	ADDI P4,(T2)		;First word after BLT
	XCTR XBLTW,[BLT T1,(P4)] ;Transfer one IMP buffer
	HRRZ P1,(P1)		;Advance to next buffer
	JUMPE P2,UDPRE3		;Unless done
	JUMPN P1,UDPRE2		;Make sure there is a buffer
	PUSHJ P,BUGTRP		;Oops!
	JRST UDPRE4		;Just exit quietly if continued

UDPRE3:	JUMPE P1,.+2		;If done, there should be no buffers
	PUSHJ P,BUGTRP		;Wrong again
UDPRE4:	MOVE T1,IBFTHS(F)	;Get pointer to buffer stream
	PUSHJ P,RELBUF↑		;Release them all
	SETZM IBFTHS(F)
	POPJ P,

;Here to flush packet pointed to by DDB.
UDPFLS:	PUSHJ P,SAVT↑		;Get T-registers (restored on return from RELBUF)
	HRRZ T1,IBFTHS(DDB)	;Point to beginning of buffer stream
	JRST RELBUF↑		;(in NETSUB.MAC)

;Here to wait for a packet (ACs in TOPS-10 mode).
UDPREW:	LDB T1,INPTP		;Get input wait time
	LSH T1,2		;Convert to seconds
	PUSHJ P,IMPWAT		;Wait for data
	TRNN S,TMO		;Check for timeout
	JRST CPOPJ1		;No, should be OK
;JJW - do we need to do this?
	MOVEI S,IODERR		;Set error bit with timeout
	IORB S,DEVIOS(F)
	POPJ P,
;MTAPE to get a free UDP local port number, stored in word 1 of MTAPE block ;⊗ GENUDP UDPPRT UDPPR1 UDPPR2

GENUDP:	PUSHJ P,UDPPRT		;Get a free UDP port
	XCTR XW,[MOVEM TAC,1(UUO)]
	POPJ P,

UDPPRT:	AOS TAC,UDFPRT		;Get next port number
	TRNN TAC,200000		;Skip if more than 16 bits
	JRST UDPPR1
	MOVEI TAC,UDRPRT	;Reserve well-known ports
	MOVEM TAC,UDFPRT
UDPPR1:	MOVEI TAC1,IMPDDB	;Start search through DDBs
UDPPR2:	HLRZ TAC1,DEVSER(TAC1)	;Get next DDB
	CAIN TAC1,IMP.NX	;End of IMP DDBs?
	POPJ P,			;Yes, done
	CAMN TAC,LCLPRT(TAC1)	;Is port the same?
	JRST UDPPRT		;Yes, try all over again
	JRST UDPPR2		;Keep checking